/**
 * Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
 * @brief FreeRTOS应用示例
 * @details
 * @author 王炸物联网https://blog.csdn.net/wangyx1234?spm=1000.2115.3001.5343
 * @date 2022
 * @version 1.0
 * @copyright 版权所有，禁止用于商业用途
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/stream_buffer.h"
#include "freertos/message_buffer.h"

#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"

#include "driver/gpio.h"
#include "esp_rom_sys.h"

#define TASK_TAG1      "TASK1"
#define TASK_TAG2      "TASK2"

#define CUSTOM_TRIGGER_LEVEL (10)

TaskHandle_t task1; // 任务1结构对象
TaskHandle_t task2; // 任务1结构对象  

static uint8_t task1_flag;
static uint8_t task2_flag;

static MessageBufferHandle_t xMessageBuffer;
SemaphoreHandle_t end_test;

/*display buffer in hex on a line*/
void disp_buf(const char* TAG, uint8_t* buf, uint32_t len)
{
    int i;
    assert(buf != NULL);
    printf("%s: The buffer data is as follows:", TAG);
    for (i = 0; i < len; i++) {
        printf("%02x ", buf[i]);//when finished the test, the printf() will be change to ESP_LOGD();
        if ((i + 1) % 16 == 0) {
            printf("\n");
        }
    }
    printf("\n");
}

/**
 * 任务的运行代码
 * @param param 任务初始运行参数
 */
static void task1_process(void *arg)
{
    static const char *TASK1_TAG = TASK_TAG1;
    uint8_t ArrayToSend1[] = { 0, 1, 2, 3 };
    uint8_t ArrayToSend2[] = { 4, 5, 6, 7, 8, 9};
    size_t xBytesSent = 0;
    uint8_t *p_send = NULL;
    uint32_t p_send_count = 0;

    BaseType_t result;
    while (1) {
        if(task1_flag%2) {
            p_send = ArrayToSend2;
            p_send_count = sizeof(ArrayToSend2);
            printf("%s: array is 2\n", TASK1_TAG);
        } else {
            p_send = ArrayToSend1;
            p_send_count = sizeof(ArrayToSend1);
            printf("%s: array is 1\n", TASK1_TAG);
        }
        
         // Send an array to the message buffer, blocking for a maximum of 100ms to
        // wait for enough space to be available in the message buffer.
        xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) p_send, p_send_count,  pdMS_TO_TICKS(100) );
         if(xBytesSent != p_send_count){
            // The call to xMessageBufferSend() times out before there was enough
            // space in the buffer for the data to be written.
            printf("%s: send count err\n", TASK1_TAG);
        }

        task1_flag++;
        if(task1_flag > 4) {
            xSemaphoreGive(end_test);
            vTaskDelete(NULL);
        }
        
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

/**
 * 任务的运行代码
 * @param param 任务初始运行参数
 */
static void task2_process(void *arg)
{
    static const char *TASK2_TAG = TASK_TAG2;
    uint8_t ucRxData[20];
    size_t xReceivedBytes;

    while (1) {
        xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
                                         ( void *) ucRxData,
                                         sizeof(ucRxData),
                                         portMAX_DELAY);

        if( xReceivedBytes > 0 )
        {
            // A ucRxData contains a message that is xReceivedBytes long.  Process
            // the message here....
            printf("%s: receive length is %u\r\n",TASK2_TAG, xReceivedBytes);
            disp_buf(TASK2_TAG, ucRxData, xReceivedBytes);
        } else {
            printf("%s: receive err\r\n",TASK2_TAG);
        }

        if(xSemaphoreTake(end_test, 0)) {
            vMessageBufferDelete(xMessageBuffer);
            vSemaphoreDelete(end_test);
            vTaskDelete(NULL);
        }

        task2_flag++;
    }
}

static void init(void) {
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());

   xMessageBuffer = xMessageBufferCreate(256);
   end_test = xSemaphoreCreateBinary();

    if ((xMessageBuffer == NULL) || (end_test == NULL)) {
        printf("sb or sem created fail\n");
    } 
    xMessageBufferReset(xMessageBuffer);
}

void app_main(void)
{
    init();
    /*
    static BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *constpcName, const uint32_t usStackDepth, 
    void *constpvParameters, UBaseType_t uxPriority, TaskHandle_t *constpxCreatedTask)*/
    xTaskCreatePinnedToCore(&task1_process, "task1", 1024*2, (void *)"1", configMAX_PRIORITIES-1, &task1, 0); // configMAX_PRIORITIES = 25
    xTaskCreatePinnedToCore(&task2_process, "task2", 1024*2, (void *)"2", configMAX_PRIORITIES-2, &task2, 1); // configMAX_PRIORITIES = 25
}
